package it3807.semOppg1;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

import org.apache.lucene.document.Document;
import org.apache.lucene.search.Hits;

public class RequestServer extends Thread {
	private int port;
	private DocSearch search;
	public RequestServer(int port, DocSearch search) {
		this.port = port;
		this.search = search;
		this.start();
	}
	
	public void run() {
		ServerSocket serverSocket = null;
		Logger.info(this, "Binding port " + port);
		try {
			serverSocket = new ServerSocket(port);
		} catch (IOException e) {
			Logger.warn(this, "Unable to bind port, " + e.getMessage());
			return;
		}
		
		while (true) {
			Logger.info(this, "Waiting for search requests...");
			Socket connSocket = null;
			try {
				connSocket = serverSocket.accept();
				InetAddress clientIp = connSocket.getInetAddress();
				Logger.info(this, "Connection from " + clientIp.getHostAddress());
				
				// read input from client
				BufferedReader input = new BufferedReader( 
						new InputStreamReader(connSocket.getInputStream()));
				
				// open for output to client
				DataOutputStream output = new DataOutputStream(connSocket.getOutputStream());
				
				handleRequest(input, output);
				output.close();
				input.close();
				
			} catch (IOException e) {
				Logger.warn(this, "Client IO problem: " + e.getMessage());
			}
			
		}
	}

	private void handleRequest(BufferedReader input, DataOutputStream output) {
		String querystr;
		
		try {
			querystr = input.readLine();
		} catch (IOException e) {
			Logger.warn(this, 
				"Error reading request, ignoring. Error: " + e.getMessage());
			return;
		}
		
		Hits hits = search.searchCombined(querystr);
		streamSearchHits(output, hits);
	}

	private void streamSearchHits(DataOutputStream output, Hits hits) {
		
		for (int i = 0; i < hits.length(); i++) {
			Document doc = null;
			float score = -1;
			try {
				doc = hits.doc(i);
				score = hits.score(i);
			} catch (Exception e) {
				Logger.warn(this, "Error with searchResult document: " + e.getMessage());
				continue;
			}
			
			try {
				output.writeChars("NEW_RESULT_START\n");
				output.writeChars("score:" + score + "\n");
				output.writeChars("imgpath:" + 
						doc.get(DocIndexer.FIELD_DOC_IMGPATH) + "\n");
				output.writeChars("docname:" +
						doc.get(DocIndexer.FIELD_DOC_NAME) + "\n");
				output.writeChars("docpath:" + 
						doc.get(DocIndexer.FIELD_DOC_PATH) + "\n");
				output.writeChars("imgalt:" + 
						doc.get(DocIndexer.FIELD_DOC_ALT) + "\n");
				/*output.writeChars(doc.get(DocIndexer.FIELD_DOC_NAME) + "\n");
				output.writeChars(doc.get(DocIndexer.FIELD_DOC_PATH) + "\n");*/
			} catch (IOException e) {
				Logger.warn(this, "Error writing to connection " + e.getMessage());
				return;
			}
		}	
	}

}
